package certs

import (
	"context"
	"crypto/x509"
	"net"
	"strings"
	"testing"

	"gopkg.openfuyao.cn/bkeagent/utils/pkiutil"
	confv1beta1 "gopkg.openfuyao.cn/bkecommon/cluster/api/v1beta1"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	certutil "k8s.io/client-go/util/cert"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"

	bkev1beta1 "gopkg.openfuyao.cn/cluster-api-provider-bke/api/v1beta1"
)

const (
	testIPAddress1   = "127.0.0.1"
	testHADomain     = "ha.example.com"
	testEndpointPort = 6443
	testEndpoint1    = testIPAddress1 + ":6443"
)

var bkeCluster = &bkev1beta1.BKECluster{
	TypeMeta: metav1.TypeMeta{
		Kind:       "BKECluster",
		APIVersion: "bke.bocloud.com/v1beta1",
	},
	ObjectMeta: metav1.ObjectMeta{
		Name:      "test",
		Namespace: "default",
		UID:       "test",
	},
	Spec: confv1beta1.BKEClusterSpec{
		ControlPlaneEndpoint: confv1beta1.APIEndpoint{
			Host: testIPAddress1,
			Port: testEndpointPort,
		},
		ClusterConfig: &confv1beta1.BKEConfig{
			Cluster: confv1beta1.Cluster{
				ControlPlane: confv1beta1.ControlPlane{
					Etcd: &confv1beta1.Etcd{
						ServerCertSANs: []string{"1.1.1.1", "abc.com"},
					},
					APIServer: &confv1beta1.APIServer{
						CertSANs: []string{"2.2.2.2", "def.com"},
					},
				},
			},
		},
	},
}

// createTestGenerator creates a test BKEKubernetesCertGenerator instance with a fake client
func createTestGenerator() *BKEKubernetesCertGenerator {
	scheme := runtime.NewScheme()
	_ = bkev1beta1.AddToScheme(scheme)
	fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
	return NewKubernetesCertGenerator(context.TODO(), fakeClient, bkeCluster)
}

// TestPrepareBKEKubeConfigs tests that prepareBKEKubeConfigs appends kubeconfigs and renames them correctly
func TestPrepareBKEKubeConfigs(t *testing.T) {
	generator := createTestGenerator()
	initialCount := len(generator.bkeCerts)

	generator.prepareBKEKubeConfigs()

	if len(generator.bkeCerts) <= initialCount {
		t.Error("prepareBKEKubeConfigs() should append kubeconfigs")
	}

	for _, cert := range generator.bkeCerts {
		if cert.Name == "kubeconfig" {
			t.Error("prepareBKEKubeConfigs() should rename kubeconfig to admin")
		}
		if cert.CAName == "" {
			t.Error("prepareBKEKubeConfigs() should set CAName")
		}
	}
}

// TestHasAnyConfig tests the hasAnyConfig function with various configuration states
func TestHasAnyConfig(t *testing.T) {
	generator := createTestGenerator()

	tests := []struct {
		name string
		cfg  *CertConfigData
		want bool
	}{
		{
			name: "nil config",
			cfg:  nil,
			want: false,
		},
		{
			name: "config with available keys",
			cfg: &CertConfigData{
				AvailableKeys: map[string]bool{
					"key1": true,
				},
			},
			want: true,
		},
		{
			name: "config with no available keys",
			cfg: &CertConfigData{
				AvailableKeys: map[string]bool{
					"key1": false,
				},
			},
			want: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := generator.hasAnyConfig(tt.cfg)
			if got != tt.want {
				t.Errorf("hasAnyConfig() = %v, want %v", got, tt.want)
			}
		})
	}
}

// TestCanApplyConfig tests the canApplyConfig function with various states
func TestCanApplyConfig(t *testing.T) {
	generator := createTestGenerator()

	tests := []struct {
		name     string
		bkeCerts pkiutil.Certificates
		cfg      *CertConfigData
		want     bool
	}{
		{
			name:     "bkeCerts is nil",
			bkeCerts: nil,
			cfg:      &CertConfigData{AvailableKeys: make(map[string]bool)},
			want:     false,
		},
		{
			name:     "cfg is nil",
			bkeCerts: pkiutil.Certificates{pkiutil.BKECertRootCA()},
			cfg:      nil,
			want:     false,
		},
		{
			name:     "both bkeCerts and cfg are nil",
			bkeCerts: nil,
			cfg:      nil,
			want:     false,
		},
		{
			name:     "both bkeCerts and cfg are valid",
			bkeCerts: pkiutil.Certificates{pkiutil.BKECertRootCA()},
			cfg:      &CertConfigData{AvailableKeys: make(map[string]bool)},
			want:     true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			generator.bkeCerts = tt.bkeCerts
			got := generator.canApplyConfig(tt.cfg)
			if got != tt.want {
				t.Errorf("canApplyConfig() = %v, want %v", got, tt.want)
			}
		})
	}
}

// TestNewCertSecretName tests the NewCertSecretName function
func TestNewCertSecretName(t *testing.T) {
	tests := []struct {
		name        string
		clusterName string
		certName    string
		want        string
	}{
		{
			name:        "normal case",
			clusterName: "test-cluster",
			certName:    "ca",
			want:        "test-cluster-ca",
		},
		{
			name:        "empty cluster name",
			clusterName: "",
			certName:    "ca",
			want:        "-ca",
		},
		{
			name:        "empty cert name",
			clusterName: "test-cluster",
			certName:    "",
			want:        "test-cluster-",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := NewCertSecretName(tt.clusterName, tt.certName)
			if got != tt.want {
				t.Errorf("NewCertSecretName() = %v, want %v", got, tt.want)
			}
		})
	}
}

// TestHasServerAuth tests the HasServerAuth function
func TestHasServerAuth(t *testing.T) {
	serverAuthCert := createTestCertWithServerAuth()
	clientAuthCert := createTestCertWithClientAuth()
	noAuthCert := createTestCertWithoutAuth()

	tests := []struct {
		name string
		cert *x509.Certificate
		want bool
	}{
		{
			name: "cert with server auth",
			cert: serverAuthCert,
			want: true,
		},
		{
			name: "cert with client auth only",
			cert: clientAuthCert,
			want: false,
		},
		{
			name: "cert without auth",
			cert: noAuthCert,
			want: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := HasServerAuth(tt.cert)
			if got != tt.want {
				t.Errorf("HasServerAuth() = %v, want %v", got, tt.want)
			}
		})
	}
}

// TestGetExtraAltNames tests the getExtraAltNames function
func TestGetExtraAltNames(t *testing.T) {
	scheme := runtime.NewScheme()
	_ = bkev1beta1.AddToScheme(scheme)
	fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()

	clusterWithEndpoint := &bkev1beta1.BKECluster{
		Spec: confv1beta1.BKEClusterSpec{
			ControlPlaneEndpoint: confv1beta1.APIEndpoint{
				Host: testIPAddress1,
				Port: testEndpointPort,
			},
		},
	}

	clusterWithoutEndpoint := &bkev1beta1.BKECluster{
		Spec: confv1beta1.BKEClusterSpec{},
	}

	tests := []struct {
		name       string
		bkeCluster *bkev1beta1.BKECluster
		want       []string
	}{
		{
			name:       "cluster with valid endpoint",
			bkeCluster: clusterWithEndpoint,
			want:       []string{testIPAddress1},
		},
		{
			name:       "cluster without endpoint",
			bkeCluster: clusterWithoutEndpoint,
			want:       []string{},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			generator := NewKubernetesCertGenerator(context.TODO(), fakeClient, tt.bkeCluster)
			got := generator.getExtraAltNames()
			if !equalStringSlices(got, tt.want) {
				t.Errorf("getExtraAltNames() = %v, want %v", got, tt.want)
			}
		})
	}
}

// TestFillInCertificateContent tests the fillInCertificateContent function
func TestFillInCertificateContent(t *testing.T) {
	fakeClient := createFakeClientForTest()
	testCertBytes := []byte("test-cert")
	testKeyBytes := []byte("test-key")
	certName := "test-cert"
	tests := getFillInCertificateContentTestCases()

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			generator := NewKubernetesCertGenerator(context.TODO(), fakeClient, bkeCluster)
			generator.fillInCertificateContent(testCertBytes, testKeyBytes, certName, tt.isCA)
			verifyFillInCertificateContent(t, generator, certName, testCertBytes, tt.checkCA)
		})
	}
}

// getFillInCertificateContentTestCases returns test cases for fillInCertificateContent
func getFillInCertificateContentTestCases() []struct {
	name    string
	isCA    bool
	checkCA bool
} {
	return []struct {
		name    string
		isCA    bool
		checkCA bool
	}{
		{
			name:    "CA certificate",
			isCA:    true,
			checkCA: true,
		},
		{
			name:    "non-CA certificate",
			isCA:    false,
			checkCA: false,
		},
	}
}

// verifyFillInCertificateContent verifies the certificate content was filled correctly
func verifyFillInCertificateContent(t *testing.T, generator *BKEKubernetesCertGenerator, certName string, testCertBytes []byte, checkCA bool) {
	if checkCA {
		verifyCACertificateContent(t, generator, certName, testCertBytes)
	} else {
		verifyNonCACertificateContent(t, generator, certName, testCertBytes)
	}
}

// verifyCACertificateContent verifies CA certificate content
func verifyCACertificateContent(t *testing.T, generator *BKEKubernetesCertGenerator, certName string, testCertBytes []byte) {
	if generator.caCertificatesContent == nil {
		t.Error("caCertificatesContent should not be nil")
	}
	if data, ok := generator.caCertificatesContent[certName]; !ok {
		t.Error("CA certificate should be in caCertificatesContent")
	} else if string(data[TLSCrtDataName]) != string(testCertBytes) {
		t.Errorf("certificate data mismatch")
	}
}

// verifyNonCACertificateContent verifies non-CA certificate content
func verifyNonCACertificateContent(t *testing.T, generator *BKEKubernetesCertGenerator, certName string, testCertBytes []byte) {
	if generator.certificatesContent == nil {
		t.Error("certificatesContent should not be nil")
	}
	if data, ok := generator.certificatesContent[certName]; !ok {
		t.Error("certificate should be in certificatesContent")
	} else if string(data[TLSCrtDataName]) != string(testCertBytes) {
		t.Errorf("certificate data mismatch")
	}
}

// createFakeClientForTest creates a fake client for testing
func createFakeClientForTest() client.Client {
	scheme := runtime.NewScheme()
	_ = bkev1beta1.AddToScheme(scheme)
	return fake.NewClientBuilder().WithScheme(scheme).Build()
}

// TestValidateGlobalCASecret tests the validateGlobalCASecret function
func TestValidateGlobalCASecret(t *testing.T) {
	scheme := runtime.NewScheme()
	_ = bkev1beta1.AddToScheme(scheme)
	fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
	generator := NewKubernetesCertGenerator(context.TODO(), fakeClient, bkeCluster)

	validCertBytes, validKeyBytes := createValidTestCertAndKey()
	invalidCertBytes := []byte("invalid-cert")

	tests := []struct {
		name    string
		secret  *corev1.Secret
		wantErr bool
	}{
		{
			name:    "valid secret",
			secret:  createSecretWithData(validCertBytes, validKeyBytes),
			wantErr: false,
		},
		{
			name:    "secret with nil data",
			secret:  &corev1.Secret{Data: nil},
			wantErr: true,
		},
		{
			name:    "secret missing cert",
			secret:  createSecretWithData(nil, validKeyBytes),
			wantErr: true,
		},
		{
			name:    "secret missing key",
			secret:  createSecretWithData(validCertBytes, nil),
			wantErr: true,
		},
		{
			name:    "secret with empty cert",
			secret:  createSecretWithData([]byte{}, validKeyBytes),
			wantErr: true,
		},
		{
			name:    "secret with invalid cert",
			secret:  createSecretWithData(invalidCertBytes, validKeyBytes),
			wantErr: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := generator.validateGlobalCASecret(tt.secret)
			if (err != nil) != tt.wantErr {
				t.Errorf("validateGlobalCASecret() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

// TestApplyAltNamesToCert tests the applyAltNamesToCert function
func TestApplyAltNamesToCert(t *testing.T) {

	generator := createTestGenerator()
	cert := pkiutil.BKECertAPIServer()
	altNames := &certutil.AltNames{
		DNSNames: []string{"test.example.com"},
		IPs:      []net.IP{net.ParseIP(testIPAddress1)},
	}
	extraAltNames := []string{"extra.example.com"}

	err := generator.applyAltNamesToCert(cert, altNames, extraAltNames)
	if err != nil {
		t.Errorf("applyAltNamesToCert() error = %v", err)
	}

	if len(cert.Config.AltNames.DNSNames) == 0 {
		t.Error("DNSNames should not be empty")
	}
	if len(cert.Config.AltNames.IPs) == 0 {
		t.Error("IPs should not be empty")
	}
}

// createTestCertWithServerAuth creates a test certificate with server auth
func createTestCertWithServerAuth() *x509.Certificate {
	return &x509.Certificate{
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
	}
}

// createTestCertWithClientAuth creates a test certificate with client auth only
func createTestCertWithClientAuth() *x509.Certificate {
	return &x509.Certificate{
		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
	}
}

// createTestCertWithoutAuth creates a test certificate without auth
func createTestCertWithoutAuth() *x509.Certificate {
	return &x509.Certificate{
		ExtKeyUsage: []x509.ExtKeyUsage{},
	}
}

// createValidTestCertAndKey creates valid test certificate and key bytes
func createValidTestCertAndKey() ([]byte, []byte) {
	cert := pkiutil.BKECertRootCA()
	caCert, caKey, _ := pkiutil.NewCertificateAuthority(cert)
	return pkiutil.EncodeCertToPEM(caCert), pkiutil.EncodeKeyToPEM(caKey)
}

// createSecretWithData creates a secret with certificate and key data
func createSecretWithData(certBytes, keyBytes []byte) *corev1.Secret {
	data := make(map[string][]byte)
	if len(certBytes) > 0 {
		data[TLSCrtDataName] = certBytes
	}
	if len(keyBytes) > 0 {
		data[TLSKeyDataName] = keyBytes
	}
	return &corev1.Secret{Data: data}
}

// equalStringSlices checks if two string slices are equal
func equalStringSlices(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

// TestConfigKubeConfig tests the ConfigKubeConfig function
func TestConfigKubeConfig(t *testing.T) {

	generator := createTestGenerator()
	tests := []struct {
		name           string
		endpoint       string
		expectedResult string
	}{
		{
			name:           "empty endpoint uses default",
			endpoint:       "",
			expectedResult: bkeCluster.Spec.ControlPlaneEndpoint.String(),
		},
		{
			name:           "non-empty endpoint",
			endpoint:       testEndpoint1,
			expectedResult: testEndpoint1,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			generator.ConfigKubeConfig(tt.endpoint)
			if generator.kubeConfigEndpoint != tt.expectedResult {
				t.Errorf("kubeConfigEndpoint = %v, want %v", generator.kubeConfigEndpoint, tt.expectedResult)
			}
			if !generator.needCreateKubeConfig {
				t.Error("needCreateKubeConfig should be true")
			}
		})
	}
}

// TestSetCertsCAName tests the SetCertsCAName function
func TestSetCertsCAName(t *testing.T) {
	generator := createTestGenerator()
	tests := []struct {
		name           string
		isUserCustomCA bool
		bkeCerts       pkiutil.Certificates
		expectCAName   string
	}{
		{
			name:           "isUserCustomCA true with CA cert",
			isUserCustomCA: true,
			bkeCerts:       pkiutil.Certificates{pkiutil.BKECertRootCA()},
			expectCAName:   "global-ca",
		},
		{
			name:           "isUserCustomCA false with CA cert",
			isUserCustomCA: false,
			bkeCerts:       pkiutil.Certificates{pkiutil.BKECertRootCA()},
			expectCAName:   "",
		},
		{
			name:           "isUserCustomCA true with FrontProxyCA",
			isUserCustomCA: true,
			bkeCerts:       pkiutil.Certificates{pkiutil.BKECertFrontProxyCA()},
			expectCAName:   "global-ca",
		},
		{
			name:           "isUserCustomCA true with EtcdCA",
			isUserCustomCA: true,
			bkeCerts:       pkiutil.Certificates{pkiutil.BKECertEtcdCA()},
			expectCAName:   "global-ca",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			generator.bkeCerts = tt.bkeCerts
			generator.isUserCustomCA = tt.isUserCustomCA
			generator.SetCertsCAName()

			if len(generator.bkeCerts) > 0 {
				cert := generator.bkeCerts[0]
				if cert.CAName != tt.expectCAName {
					t.Errorf("CAName = %v, want %v", cert.CAName, tt.expectCAName)
				}
			}
		})
	}
}

// TestIsHACluster tests the IsHACluster function
func TestIsHACluster(t *testing.T) {
	tests := getIsHAClusterTestCases()

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := IsHACluster(tt.bkeCluster)
			if got != tt.want {
				t.Errorf("IsHACluster() = %v, want %v", got, tt.want)
			}
		})
	}
}

// getIsHAClusterTestCases returns test cases for IsHACluster
func getIsHAClusterTestCases() []struct {
	name       string
	bkeCluster *bkev1beta1.BKECluster
	want       bool
} {
	clusterWithHAEndpoint := createClusterWithHAEndpoint()
	clusterWithNodeIP := createClusterWithNodeIP()
	clusterWithoutEndpoint := createClusterWithoutEndpoint()

	return []struct {
		name       string
		bkeCluster *bkev1beta1.BKECluster
		want       bool
	}{
		{
			name:       "HA cluster with domain endpoint",
			bkeCluster: clusterWithHAEndpoint,
			want:       true,
		},
		{
			name:       "non-HA cluster with node IP",
			bkeCluster: clusterWithNodeIP,
			want:       false,
		},
		{
			name:       "cluster without endpoint",
			bkeCluster: clusterWithoutEndpoint,
			want:       false,
		},
	}
}

// createClusterWithHAEndpoint creates a cluster with HA endpoint
func createClusterWithHAEndpoint() *bkev1beta1.BKECluster {
	return createClusterWithEndpointAndNodes(testHADomain, testIPAddress1)
}

// createClusterWithNodeIP creates a cluster with node IP endpoint
func createClusterWithNodeIP() *bkev1beta1.BKECluster {
	return createClusterWithEndpointAndNodes(testIPAddress1, testIPAddress1)
}

// createClusterWithEndpointAndNodes creates a cluster with endpoint and nodes
func createClusterWithEndpointAndNodes(endpointHost, nodeIP string) *bkev1beta1.BKECluster {
	return &bkev1beta1.BKECluster{
		Spec: confv1beta1.BKEClusterSpec{
			ControlPlaneEndpoint: confv1beta1.APIEndpoint{
				Host: endpointHost,
				Port: testEndpointPort,
			},
			ClusterConfig: &confv1beta1.BKEConfig{
				Nodes: []confv1beta1.Node{
					{IP: nodeIP},
				},
			},
		},
	}
}

// createClusterWithoutEndpoint creates a cluster without endpoint
func createClusterWithoutEndpoint() *bkev1beta1.BKECluster {
	return &bkev1beta1.BKECluster{
		Spec: confv1beta1.BKEClusterSpec{},
	}
}

// TestTryLoadGlobalCAFromSecret tests the tryLoadGlobalCAFromSecret function
func TestTryLoadGlobalCAFromSecret(t *testing.T) {
	scheme := createSchemeWithCoreV1ForTest()
	generator := createTestGenerator()
	tests := getTryLoadGlobalCATestCases(scheme)

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			generator.client = tt.clientSetup()
			data, found, err := generator.tryLoadGlobalCAFromSecret()
			result := tryLoadGlobalCAResult{
				data:        data,
				found:       found,
				err:         err,
				expectFound: tt.expectFound,
				expectError: tt.expectError,
			}
			verifyTryLoadGlobalCAResult(t, result)
		})
	}
}

// getTryLoadGlobalCATestCases returns test cases for tryLoadGlobalCAFromSecret
func getTryLoadGlobalCATestCases(scheme *runtime.Scheme) []tryLoadGlobalCATestCase {
	validSecret := createValidGlobalCASecret()
	invalidSecret := createInvalidGlobalCASecret()

	return []tryLoadGlobalCATestCase{
		createSecretNotFoundTestCase(scheme),
		createValidSecretFoundTestCase(scheme, validSecret),
		createInvalidSecretDataTestCase(scheme, invalidSecret),
	}
}

// tryLoadGlobalCATestCase represents a test case for tryLoadGlobalCAFromSecret
type tryLoadGlobalCATestCase struct {
	name        string
	clientSetup func() client.Client
	expectFound bool
	expectError bool
}

// createSecretNotFoundTestCase creates a test case for secret not found
func createSecretNotFoundTestCase(scheme *runtime.Scheme) tryLoadGlobalCATestCase {
	return tryLoadGlobalCATestCase{
		name:        "secret not found",
		clientSetup: func() client.Client { return fake.NewClientBuilder().WithScheme(scheme).Build() },
		expectFound: false,
		expectError: false,
	}
}

// createValidSecretFoundTestCase creates a test case for valid secret found
func createValidSecretFoundTestCase(scheme *runtime.Scheme, validSecret *corev1.Secret) tryLoadGlobalCATestCase {
	return tryLoadGlobalCATestCase{
		name: "valid secret found",
		clientSetup: func() client.Client {
			return fake.NewClientBuilder().WithScheme(scheme).WithObjects(validSecret).Build()
		},
		expectFound: true,
		expectError: false,
	}
}

// createInvalidSecretDataTestCase creates a test case for invalid secret data
func createInvalidSecretDataTestCase(scheme *runtime.Scheme, invalidSecret *corev1.Secret) tryLoadGlobalCATestCase {
	return tryLoadGlobalCATestCase{
		name: "invalid secret data",
		clientSetup: func() client.Client {
			return fake.NewClientBuilder().WithScheme(scheme).WithObjects(invalidSecret).Build()
		},
		expectFound: false,
		expectError: false,
	}
}

// createValidGlobalCASecret creates a valid global CA secret
func createValidGlobalCASecret() *corev1.Secret {
	validCertBytes, validKeyBytes := createValidTestCertAndKey()
	secret := createSecretWithData(validCertBytes, validKeyBytes)
	secret.Namespace = GlobalCANamespace
	secret.Name = GlobalCASecretName
	return secret
}

// createInvalidGlobalCASecret creates an invalid global CA secret
func createInvalidGlobalCASecret() *corev1.Secret {
	return &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Namespace: GlobalCANamespace,
			Name:      GlobalCASecretName,
		},
		Data: nil,
	}
}

// createGeneratorForGlobalCATest creates a generator for global CA tests
func createGeneratorForGlobalCATest(scheme *runtime.Scheme) *BKEKubernetesCertGenerator {
	fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
	return NewKubernetesCertGenerator(context.TODO(), fakeClient, bkeCluster)
}

// createSchemeWithCoreV1ForTest creates a scheme with CoreV1 for testing
func createSchemeWithCoreV1ForTest() *runtime.Scheme {
	return createSchemeWithCoreV1()
}

// tryLoadGlobalCAResult represents the result of tryLoadGlobalCAFromSecret
type tryLoadGlobalCAResult struct {
	data        map[string][]byte
	found       bool
	err         error
	expectFound bool
	expectError bool
}

// verifyTryLoadGlobalCAResult verifies the result of tryLoadGlobalCAFromSecret
func verifyTryLoadGlobalCAResult(t *testing.T, result tryLoadGlobalCAResult) {
	verifyTryLoadGlobalCAError(t, result.err, result.expectError)
	verifyTryLoadGlobalCAFound(t, result.found, result.expectFound)
	verifyTryLoadGlobalCAData(t, result.data, result.expectFound)
}

// verifyTryLoadGlobalCAError verifies the error result
func verifyTryLoadGlobalCAError(t *testing.T, err error, expectError bool) {
	if expectError && err == nil {
		t.Errorf("tryLoadGlobalCAFromSecret() expected error but got nil")
	}
	if !expectError && err != nil {
		t.Errorf("tryLoadGlobalCAFromSecret() unexpected error = %v", err)
	}
}

// verifyTryLoadGlobalCAFound verifies the found result
func verifyTryLoadGlobalCAFound(t *testing.T, found, expectFound bool) {
	if found != expectFound {
		t.Errorf("tryLoadGlobalCAFromSecret() found = %v, want %v", found, expectFound)
	}
}

// verifyTryLoadGlobalCAData verifies the data result
func verifyTryLoadGlobalCAData(t *testing.T, data map[string][]byte, expectFound bool) {
	if expectFound && data == nil {
		t.Error("tryLoadGlobalCAFromSecret() should return data when found")
	}
}

// TestCreateGlobalCASecret tests the createGlobalCASecret function
func TestCreateGlobalCASecret(t *testing.T) {
	scheme := createSchemeWithCoreV1()
	testData := createTestGlobalCAData()
	tests := getCreateGlobalCASecretTestCases(scheme)

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			runCreateGlobalCASecretTest(t, tt, testData)
		})
	}
}

// getCreateGlobalCASecretTestCases returns test cases for createGlobalCASecret
func getCreateGlobalCASecretTestCases(scheme *runtime.Scheme) []createGlobalCASecretTestCase {
	return []createGlobalCASecretTestCase{
		createSuccessfulCreateTestCase(scheme),
		createAlreadyExistsTestCase(scheme),
	}
}

// createGlobalCASecretTestCase represents a test case for createGlobalCASecret
type createGlobalCASecretTestCase struct {
	name          string
	bkeCluster    *bkev1beta1.BKECluster
	clientSetup   func() client.Client
	expectError   bool
	expectErrType string
}

// createSuccessfulCreateTestCase creates a test case for successful creation
func createSuccessfulCreateTestCase(scheme *runtime.Scheme) createGlobalCASecretTestCase {
	return createGlobalCASecretTestCase{
		name:       "successful create with bkeCluster",
		bkeCluster: bkeCluster,
		clientSetup: func() client.Client {
			return fake.NewClientBuilder().WithScheme(scheme).Build()
		},
		expectError: false,
	}
}

// createAlreadyExistsTestCase creates a test case for already exists error
func createAlreadyExistsTestCase(scheme *runtime.Scheme) createGlobalCASecretTestCase {
	return createGlobalCASecretTestCase{
		name:       "already exists error",
		bkeCluster: bkeCluster,
		clientSetup: func() client.Client {
			return &alreadyExistsClient{Client: fake.NewClientBuilder().WithScheme(scheme).Build()}
		},
		expectError:   true,
		expectErrType: "already exists",
	}
}

// runCreateGlobalCASecretTest runs a single test case for createGlobalCASecret
func runCreateGlobalCASecretTest(t *testing.T, tt createGlobalCASecretTestCase, testData map[string][]byte) {
	fakeClient := tt.clientSetup()
	generator := NewKubernetesCertGenerator(context.TODO(), fakeClient, tt.bkeCluster)
	err := generator.createGlobalCASecret(testData)
	verifyCreateGlobalCASecretError(t, err, tt.expectError, tt.expectErrType)
}

// TestLoadCaCertContent tests the loadCaCertContent function
func TestLoadCaCertContent(t *testing.T) {
	scheme := createSchemeWithCoreV1ForTest()
	caSecret := createTestCASecret()
	tests := getLoadCaCertContentTestCases(scheme, caSecret)

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			runLoadCaCertContentTest(t, tt)
		})
	}
}

// getLoadCaCertContentTestCases returns test cases for loadCaCertContent
func getLoadCaCertContentTestCases(scheme *runtime.Scheme, caSecret *corev1.Secret) []loadCaCertContentTestCase {
	return []loadCaCertContentTestCase{
		createSecretsNotFoundTestCase(scheme),
		createSecretFoundTestCase(scheme, caSecret),
	}
}

// loadCaCertContentTestCase represents a test case for loadCaCertContent
type loadCaCertContentTestCase struct {
	name        string
	clientSetup func() client.Client
	expectError bool
}

// createSecretsNotFoundTestCase creates a test case for secrets not found
func createSecretsNotFoundTestCase(scheme *runtime.Scheme) loadCaCertContentTestCase {
	return loadCaCertContentTestCase{
		name: "secrets not found",
		clientSetup: func() client.Client {
			return fake.NewClientBuilder().WithScheme(scheme).Build()
		},
		expectError: false,
	}
}

// createSecretFoundTestCase creates a test case for secret found
func createSecretFoundTestCase(scheme *runtime.Scheme, caSecret *corev1.Secret) loadCaCertContentTestCase {
	return loadCaCertContentTestCase{
		name: "secret found and loaded",
		clientSetup: func() client.Client {
			return fake.NewClientBuilder().WithScheme(scheme).WithObjects(caSecret).Build()
		},
		expectError: false,
	}
}

// createTestCASecret creates a test CA secret
func createTestCASecret() *corev1.Secret {
	validCertBytes, validKeyBytes := createValidTestCertAndKey()
	caSecret := createSecretWithData(validCertBytes, validKeyBytes)
	caSecret.Namespace = "default"
	caSecret.Name = "test-ca"
	return caSecret
}

// runLoadCaCertContentTest runs a single test case for loadCaCertContent
func runLoadCaCertContentTest(t *testing.T, tt loadCaCertContentTestCase) {
	generator := NewKubernetesCertGenerator(context.TODO(), tt.clientSetup(), bkeCluster)
	generator.certClusterName = "test"
	err := generator.loadCaCertContent()
	verifyLoadCaCertContentError(t, err, tt.expectError)
}

// verifyLoadCaCertContentError verifies the error from loadCaCertContent
func verifyLoadCaCertContentError(t *testing.T, err error, expectError bool) {
	if (err != nil) != expectError {
		t.Errorf("loadCaCertContent() error = %v, wantErr %v", err, expectError)
	}
}

// createSchemeWithCoreV1 creates a scheme with CoreV1 and BKE types
func createSchemeWithCoreV1() *runtime.Scheme {
	scheme := runtime.NewScheme()
	_ = bkev1beta1.AddToScheme(scheme)
	_ = corev1.AddToScheme(scheme)
	return scheme
}

// createTestGlobalCAData creates test data for global CA
func createTestGlobalCAData() map[string][]byte {
	return map[string][]byte{
		TLSCrtDataName: []byte("test-cert"),
		TLSKeyDataName: []byte("test-key"),
	}
}

// verifyCreateGlobalCASecretError verifies the error from createGlobalCASecret
func verifyCreateGlobalCASecretError(t *testing.T, err error, expectError bool, expectErrType string) {
	if expectError {
		if err == nil {
			t.Errorf("createGlobalCASecret() expected error but got nil")
		} else if expectErrType != "" {
			if !strings.Contains(err.Error(), expectErrType) {
				t.Errorf("createGlobalCASecret() error = %v, want error containing %v", err, expectErrType)
			}
		}
	} else {
		if err != nil {
			t.Errorf("createGlobalCASecret() unexpected error = %v", err)
		}
	}
}

// alreadyExistsClient is a test client that returns AlreadyExists error on Create
type alreadyExistsClient struct {
	client.Client
}

// Create returns AlreadyExists error for testing
func (c *alreadyExistsClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
	return apierrors.NewAlreadyExists(corev1.Resource("secret"), obj.GetName())
}
